package com.sofar.jwt.utils;

import cn.hutool.json.JSONUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.sofar.jwt.entity.TblUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;

/**
 * @author shiguorang
 * @version 1.0.0
 * @ClassName JWTUtil
 * @Description TODO
 * @createTime 2022年08月12日 14:38:00
 */
@Component
@ConfigurationProperties(prefix = "jwt")
@Slf4j
public class JWTUtil {

    /**
     * 定义token返回头
     */
    public static String header;

    /**
     * token前缀
     */
    public static String tokenPrefix;

    /**
     * 签名秘钥
     */
    public static String secret;

    /**
     * 有效期
     */
    public static Integer expireTime;

    /**
     * 存进客户端的token的key名
     */
    public static final String TOKEN = "Authorization";

    public void setHeader(String header) {
        JWTUtil.header = header;
    }

    public void setTokenPrefix(String tokenPrefix) {
        JWTUtil.tokenPrefix = tokenPrefix;
    }

    public void setSecret(String secret) {
        JWTUtil.secret = secret;
    }

    public void setExpireTime(int expireTimeInt) {
        JWTUtil.expireTime = expireTimeInt;
    }

    /**
     * 创建token
     * @param user
     * @return
     */
    public static String createToken(TblUser user){
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.HOUR,expireTime);
        return tokenPrefix + JWT.create()
                  .withClaim("data", JSONUtil.toJsonStr(user))
                  .withExpiresAt(instance.getTime())
                  .sign(Algorithm.HMAC512(secret));
    }

    /**
     * 验证token
     * @param token
     * @return
     */
    public static TblUser validateToken(String token) throws Exception {
        try {
            DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC512(secret))
                    .build()
                    .verify(token.replace(tokenPrefix, ""));
            String data = decodedJWT.getClaim("data").asString();
            TblUser user = JsonUtils.json2Object(data, TblUser.class);
            return user;
        }catch (TokenExpiredException e){
            throw  new TokenExpiredException("token过期");
        }catch (Exception  e){
            throw new Exception("token验证失败");
        }
    }


    /**
     * 检查token是否需要更新
     * @param token
     * @return
     */
    public static boolean isNeedUpdate(String token) throws Exception {
        Date expiresAt = null;
        try {
            expiresAt = JWT.require(Algorithm.HMAC512(secret))
                    .build()
                    .verify(token.replace(tokenPrefix, ""))
                    .getExpiresAt();
        }catch (TokenExpiredException  e){
            return true;
        }catch (Exception e){
            throw new Exception("token验证失败");
        }
        return (expiresAt.getTime() - System.currentTimeMillis()) < (expireTime >> 1);
    }
}
